package com.miao.util;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * MD5加密
 * 单向加密算法
 * 特点：加密速度快，不需要秘钥，但是安全性不高，需要搭配随机盐值使用
 */
public class MD5Util {

    /**
     * 使用MD5算法对内容进行签名
     *
     * @param content 需要签名的内容
     * @param salt 加密用的盐，用于增加签名内容的复杂度，防止暴力破解
     * @param charset 字符集，用于将内容转换成字节数组时指定字符编码方式
     * @return 返回签名后的MD5值，以十六进制字符串形式表示
     */
    public static String sign(String content, String salt, String charset) {
        // 将内容和盐合并，以增加签名的复杂度
        content = content + salt;
        // 使用指定的字符集将合并后的内容转换成字节数组，并计算MD5哈希值，返回十六进制字符串
        return DigestUtils.md5Hex(getContentBytes(content, charset));
    }


    /**
     * 验证签名是否合法
     * 此方法主要用于验证给定的内容和签名是否匹配通过添加盐值和指定字符集来生成签名的散列值，
     * 然后将这个散列值与提供的签名进行比较，以验证数据的完整性
     *
     * @param content 要验证的内容，通常是待验证的数据字符串
     * @param sign    数据的签名，用于与生成的散列值进行比较
     * @param salt    盐值，用于增加签名的安全性，防止彩虹表攻击
     * @param charset 字符集，用于将内容转换为字节数组时指定字符编码方式
     * @return 如果生成的散列值与提供的签名相等，则返回true，表示签名合法；否则返回false
     */
    public static boolean verify(String content, String sign, String salt, String charset) {
        // 在内容末尾添加盐值，以保持与签名生成过程的一致性
        content = content + salt;
        // 生成签名的散列值，并与提供的签名进行比较
        String mysign = DigestUtils.md5Hex(getContentBytes(content, charset));
        return mysign.equals(sign);
    }

    private static byte[] getContentBytes(String content, String charset) {
        if (!"".equals(charset)) {
            try {
                return content.getBytes(charset);
            } catch (UnsupportedEncodingException var3) {
                throw new RuntimeException("MD5签名过程中出现错误,指定的编码集错误");
            }
        } else {
            return content.getBytes();
        }
    }

    //获取文件md5加密后的字符串
    public static String getFileMD5(MultipartFile file) throws Exception {
        InputStream fis = file.getInputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int byteRead;
        while((byteRead = fis.read(buffer)) > 0){
            baos.write(buffer, 0, byteRead);
        }
        fis.close();
        return DigestUtils.md5Hex(baos.toByteArray());
    }

    public static void main(String[] args) {
        String password = "123456";
        String salt = String.valueOf(new Date().getTime());
        String decodePassword = MD5Util.sign(password, salt, "UTF-8");
        System.out.println(decodePassword);

        boolean verify = MD5Util.verify("1234567", decodePassword, salt, "UTF-8");
        System.out.println(verify);
    }
}